import { $ } from "koishi"

export const name = "-dgck81lnn-nasiara-crawler"
export const inject = ["http", "database", "cron"]

const config = {
  http: {
    headers: {
      "User-Agent": "nasiara-crawler/0.1 (DGCK81LNN <triluolnn@163.com>) LNNBot/0",
    },
  },
  maxExcludes: 3000,
}

export function apply(ctx) {
  ctx.model.extend("dgck81lnn-nasiara-crawler", {
    word: "string(63)",
    ctime: "timestamp",
    atime: "timestamp",
    times_seen: "integer",
    entry: "json",
    info_list: { type: "json", initial: null },
  }, {
    primary: "word",
  })

  const http = ctx.http.extend(config.http)

  const w = f => (...args) => {
    let r
    try {
      r = f(...args)
    } catch (e) {
      ctx.logger.error(e)
      return
    }
    if (typeof r?.then === "function") return Promise.prototype.finally.call(Promise.prototype.catch.call(r, e => ctx.logger.error(e)), () => {})
  }

  ctx.on("ready", w(async () => {
    let lookUp = true

    ctx.cron("5/10 * 0/3 * * *", w(async () => {
      const excludes = (await ctx.database.get("dgck81lnn-nasiara-crawler", {}, {
        sort: { times_seen: "desc", atime: "asc" },
        limit: config.maxExcludes,
        fields: ["word"],
      })).map(e => e.word)
      const { info } = await http.post("https://www.kouchya.top/api/nas_wordlist", { mode: "noconj", excludes })
      const now = new Date()
      await ctx.database.upsert("dgck81lnn-nasiara-crawler", row => [{
        word: info.word,
        ctime: $.ifNull(row.ctime, now),
        atime: now,
        times_seen: $.add($.ifNull(row.times_seen, 0), 1),
        entry: info.entry,
      }])
      lookUp = true
      if (excludes.length < config.maxExcludes) excludes.push(info.word)
    }))

    ctx.cron("0 * * * * *", w(async () => {
      if (!lookUp) return
      const words = (await ctx.database.get("dgck81lnn-nasiara-crawler", {
        info_list: null
      }, {
        sort: { times_seen: "desc" },
        limit: 5,
        fields: ["word"],
      })).map(e => e.word)
      if (!words.length) {
        lookUp = false
        return
      }

      const { resultList } = await http.post("https://www.kouchya.top/api/x2chn_force", { words })
      const now = new Date()
      await ctx.database.upsert("dgck81lnn-nasiara-crawler", resultList.map(result => ({
        word: result.query,
        atime: now,
        info_list: result.infoList,
      })))
    }))
  }))
}
